package com.heima.user.service.impl;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.heima.common.dto.ResponseResult;
import com.heima.common.dto.User;
import com.heima.common.enums.AppHttpCodeEnum;
import com.heima.common.util.AppJwtUtil;
import com.heima.common.util.AppThreadLocalUtil;
import com.heima.user.dto.ApAuthor;
import com.heima.user.dto.LoginDto;
import com.heima.user.dto.UserRelationDto;
import com.heima.user.entity.ApUser;
import com.heima.user.entity.ApUserFollow;
import com.heima.user.feign.ArticleClient;
import com.heima.user.mapper.ApUserMapper;
import com.heima.user.service.IApUserFollowService;
import com.heima.user.service.IApUserService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;
import org.springframework.util.StringUtils;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * <p>
 * APP用户信息表 服务实现类
 * </p>
 *
 * @author PG
 * @since 2022-06-21
 */
@Service
public class ApUserServiceImpl extends ServiceImpl<ApUserMapper, ApUser> implements IApUserService {

    @Autowired
    ArticleClient articleClient; // 文章作者的远程接口

    @Autowired
    IApUserFollowService userFollowService; // APP用户关注信息表

    /**
     * App端登录
     * @param dto
     * @return
     */
    @Override
    public ResponseResult login(LoginDto dto) {
        //1. 参数校验, 如果手机号 密码 设备id 都为空 提示参数无效
        if (dto == null ||
                (StringUtils.isEmpty(dto.getPhone())
                        && StringUtils.isEmpty(dto.getPassword())
                        && StringUtils.isEmpty(dto.getEquipmentId())
                )){
            //1.1 都为空的话提示参数无效, 直接返回
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }
        //2. 手机号和密码不为空, 使用手机号和密码登录, 流程和之前登录一样, 将查询的用户名换成手机号
        if (!StringUtils.isEmpty(dto.getPhone()) && !StringUtils.isEmpty(dto.getPassword())){
            //2.1 正常验证生成token, 根据手机号查询数据, 构建查询条件
            LambdaQueryWrapper<ApUser> query = new LambdaQueryWrapper<>();
            //2.2 手机号匹配
            query.eq(ApUser::getPhone, dto.getPhone());
            //2.3 根据手机号查询用户
            ApUser one = this.getOne(query);
            //2.4 非空判断 one == null 没查到 直接返回用户不存在
            if (one == null){
                // 返回用户不存在提示信息
                return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST);
            }
            //2.5 用户存在, 获取用户的盐, 使用用户传入的密码+salt进行MD5加密,与数据库中的密码对比
            String pwd = dto.getPassword() + one.getSalt();
            String ps = DigestUtils.md5DigestAsHex(pwd.getBytes());
            //2.6 用户输入密码 与 数据库密码匹配成功
            if (ps.equals(one.getPassword())){
                // 对比成功, 使用jwt 生成token
                // 创建 用户信息集合,
                Map<String, Object> userMap = new HashMap<>();
                //把 用户id 放里面
                userMap.put("userId", one.getId());
                // 调用方法, 生成token
                String token = AppJwtUtil.getToken(userMap);
                // 创建生成token 的集合
                Map<String, Object> map = new HashMap<>();
                // 把生成的token  放进去
                map.put("token", token);
                // 把token 返回给前端用户
                // 隐藏用户敏感信息
                one.setPassword(null);
                one.setPhone(null);
                one.setSalt(null);
                map.put("user", one);
                return ResponseResult.okResult(map);
            } else {
                // 否则返回登录错误
                return ResponseResult.errorResult(AppHttpCodeEnum.LOGIN_PASSWORD_ERROR);
            }
        }
        //2.7 如果设备id不为空, 使用 0 生成 token (游客登录, 为了能让请求通过网关)
        // 设备id 不为空  用0 生成token
        if (!StringUtils.isEmpty(dto.getEquipmentId())){
            // 游客信息集合
            Map<String, Object> userMap = new HashMap<>();
            // id 设置为0
            userMap.put("userId", 0);
            // 调用方法生成token
            String token = AppJwtUtil.getToken(userMap);
            // 创建生成token 的集合
            Map<String, Object> map = new HashMap<>();
            // 把生成的token  放进去
            map.put("token", token);
            // 把token 返回给前端用户
            return ResponseResult.okResult(map);
        }
        // 否则返回参数无效的提示信息
        return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
    }

    /**
     * 关注和取消关注
     * @param dto
     * @return
     */
    @Override
    public ResponseResult follow(UserRelationDto dto) {
        //1.从线程中获取用户信息 用户id 等
        User user = AppThreadLocalUtil.get();
        if (user == null){
            // 为空, 直接返回未登录
            return ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN);
        }
        //2. 构建 APP用户关注信息表对象
        ApUserFollow userFollow = new ApUserFollow();
        // 写入用户id, 从线程中获取
        userFollow.setUserId(user.getUserId());
        //3. 查询App用户信息表 根据用户id
        ApUser apUser = this.getById(user.getUserId());
        // 写入用户昵称, 从用户信息表中查询的用户名作为昵称
        userFollow.setUserName(apUser.getName());
        //4. 根据前端传来的作者作者id, 查询文章作者信息, 文章作者的远程接口 拿到响应结果
        ResponseResult<ApAuthor> responseResult = articleClient.getAuthorById(dto.getAuthorId());
        //4.1  //1.6 判断一下远程调用是否成功, 成功才返回数据,远程调用返回的状态码 与成功的状态码作对比
        if (responseResult.getCode().equals(AppHttpCodeEnum.SUCCESS.getCode())){
            // 调用成功, 拿到文章作者信息
            ApAuthor author = responseResult.getData();
            // 如果拿到的数据不为空, 把数据写入 APP用户关注信息表
            if (author != null){
                // 写入关注作者id, 从文章作者信息表拿到作者id
                userFollow.setFollowId(author.getUserId());
                // 写入作者昵称, 从文章作者信息表拿到作者名称
                userFollow.setFollowName(author.getName());
            }
        }
        // 写入关注度, 0代表偶尔感兴趣, 1一般, 2经常, 3高度
        userFollow.setLevel(1);
        // 写入创建时间
        userFollow.setCreatedTime(new Date());

        //5. 判断用户是否已经添加过该作者的关注记录
        // 构建查询条件
        LambdaQueryWrapper<ApUserFollow> query = new LambdaQueryWrapper<>();
        // 用户id条件
        query.eq(ApUserFollow::getUserId, userFollow.getUserId());
        //作者id条件
        query.eq(ApUserFollow::getFollowId, userFollow.getFollowId());
        // APP用户关注信息表, 进行查询
        ApUserFollow one = userFollowService.getOne(query);
        //6. 如果没查到说明没关注过, 新增关注记录
        if (one == null){
            // APP用户关注信息表, 进行保存
            userFollowService.save(userFollow);
        } else {
            // 如果是取消关注, 删除关注记录, 操作方式:Operation 0关注, 1取消
            if (dto.getOperation() == 1){
                //APP用户关注信息表, 进行 条件 删除关注记录
                userFollowService.remove(query);
            }
        }
        //last: 功能完成, 返回成功标志
        return ResponseResult.okResult();
    }
}
